<template>
  <view :id="elId" class="smt-tabs">
    <scroll-view
      :id="`scrollContainer${index}`"
      :scroll-x="scroll"
      :scroll-left="scroll ? scrollLeft : 0"
      :scroll-with-animation="scroll"
      :style="{ position: fixed ? 'fixed' : 'relative', zIndex: 10 }"
    >
      <view
        class="smt-tabs__container"
        :style="{
          display: scroll ? 'inline-flex' : 'flex',
          whiteSpace: scroll ? 'nowrap' : 'normal',
          background: bgColor,
          padding,
        }"
      >
        <view
          class="smt-tabs__container-item"
          :class="[
            'smt-tabs__container-item' + index,
            {
              'smt-tabs__container-item-pills': pills,
              'smt-tabs__container-item-pills-active': pills && current === i,
            },
          ]"
          v-for="(v, i) in tabs"
          :key="i"
          :style="{
            color:
              current == i ? (!pills ? activeColor : pillsActiveColor) : color,
            fontSize: current == i ? fontSize : fontSize,
            fontWeight: bold && current == i ? 'bold' : '',
            justifyContent: !scroll ? 'center' : '',
            flex: scroll ? '' : 1,
            padding: `${paddingItemY}rpx ${paddingItemX}rpx`,
            margin: pills ? `0 ${pillsMarginX}rpx` : '',
          }"
          @click="change(i)"
        >
          <slot name="container-item" :item="v">
            {{ field ? v[field] : v }}
          </slot>
        </view>
        <view
          v-if="!pills"
          :class="['smt-tabs__container-line', { animation: lineAnimation }]"
          :style="{
            background: getColor(lineColor),
            width: lineWidth + 'px',
            height: lineHeight,
            borderRadius: lineRadius,
            left: lineLeft + 'px',
            transform: `translateX(-${lineWidth / 2}px)`,
            bottom: lineItems ? paddingItemY + 'rpx' : '0',
          }"
        ></view>
        <view
          v-else
          :class="['smt-tabs__container-pills', { animation: lineAnimation }]"
          :style="{
            background: getColor(pillsBg, 180),
            borderRadius: pillsBorderRadius,
            left: pillsLeft + 'px',
            width: currentWidth + 'px',
            height,
          }"
        ></view>
      </view>
    </scroll-view>
    <view
      class="smt-tabs__placeholder"
      :style="{
        height: fixed ? height : '0',
        padding,
      }"
    ></view>
  </view>
</template>

<script>
import { cameTheme } from "../theme";
import { getColor } from "../utils";
/**
 * smt-tabs
 * @property {Number} value 选中的下标
 * @property {Array} tabs tabs 列表
 * @property {String} bgColor = '#fff' 背景颜色
 * @property {String} color = '#333' 默认颜色
 * @property {String} activeColor = '#2979ff' 选中文字颜色
 * @property {String} fontSize = '28rpx' 默认文字大小
 * @property {String} activeFontSize = '28rpx' 选中文字大小
 * @property {Boolean} bold = [true | false] 选中文字是否加粗
 * @property {Boolean} scroll = [true | false] 是否滚动
 * @property {String} lineHeight = '8rpx' 下划线的高度
 * @property {String | Array} lineColor = '#2979ff' 下划线的颜色(传入数组表示渐变色)
 * @property {Number} lineScale = 0.5 下划线的宽度缩放比例
 * @property {String} lineRadius = '0' 下划线圆角
 * @property {Boolean} pills = [true | false] 是否胶囊样式
 * @property {String | Array} pillsBg = '#2979ff' 胶囊背景色(传入数组表示渐变色)
 * @property {String} pillsBorderRadius = '10rpx' 胶囊圆角大小
 * @property {String} field 如果是对象，显示的键名
 * @property {Boolean} fixed = [true | false] 是否固定
 * @property {String} paddingItemX = '22' 选项的X边距
 * @property {String} paddingItemY = '22' 选项的Y边距
 * @property {Boolean} lineAnimation = [true | false] 下划线是否有动画
 * @property {Boolean} lineItems = true 下划线是否对齐字体
 * @property {Boolean} pillsActiveColor = #ffffff 胶囊状态下选中文字颜色
 * @event {Function(current)} change 改变标签触发
 */
export default {
  props: {
    // 支付宝dom获取问题
    index: {
      type: [Number, String],
      default: 0,
    },
    value: {
      type: Number,
      default: 0,
    },
    tabs: {
      type: Array,
      default() {
        return [];
      },
    },
    bgColor: {
      type: String,
      default: cameTheme.colorF,
    },
    padding: {
      type: String,
      default: "0",
    },
    color: {
      type: String,
      default: cameTheme.color3,
    },
    activeColor: {
      type: String,
      default: cameTheme.color3,
    },
    fontSize: {
      type: String,
      default: cameTheme.fontSize14,
    },
    activeFontSize: {
      type: String,
      default: cameTheme.fontSize16,
    },
    bold: {
      type: Boolean,
      default: true,
    },
    scroll: {
      type: Boolean,
      default: true,
    },
    lineColor: {
      type: [String, Array],
      default: () => ["#FEB842", "#FF9330"],
    },
    lineHeight: {
      type: String,
      default: "8rpx",
    },
    lineScale: {
      type: Number,
      default: 1,
    },
    lineRadius: {
      type: String,
      default: "0",
    },
    pills: {
      type: Boolean,
      default: false,
    },
    pillsBg: {
      type: [String, Array],
      default: () => ["#FFB600", "#FF9330"],
    },
    pillsBorderRadius: {
      type: String,
      default: "8rpx",
    },
    field: {
      type: String,
      default: "",
    },
    fixed: {
      type: Boolean,
      default: false,
    },
    paddingItemX: {
      type: String,
      default: "30",
      // 校验传入的必须是偶数
      validator(value) {
        return /^\d+$/.test(value) && value % 2 === 0;
      },
    },
    paddingItemY: {
      type: String,
      default: "20",
      // 校验传入的必须是偶数
      validator(value) {
        return /^\d+$/.test(value) && value % 2 === 0;
      },
    },
    lineAnimation: {
      type: Boolean,
      default: true,
    },
    lineItems: {
      type: Boolean,
      default: true,
    },
    pillsActiveColor: {
      type: String,
      default: cameTheme.colorF,
    },
    pillsMarginX: {
      type: String,
      default: "4",
      // 校验传入的必须是偶数
      validator(value) {
        return /^\d+$/.test(value) && value % 2 === 0;
      },
    },
  },
  data() {
    return {
      elId: "",
      lineWidth: 30,
      currentWidth: 0, // 当前选项的宽度
      lineLeft: 0, // 滑块距离左侧的位置
      pillsLeft: 0, // 胶囊距离左侧的位置
      scrollLeft: 0, // 距离左边的位置
      containerWidth: 0, // 容器的宽度
      current: 0, // 当前选中项
      height: 40, // tabs高度
    };
  },
  watch: {
    value(newVal) {
      this.current = newVal;
      this.$nextTick(() => {
        this.getTabItemWidth();
      });
    },
    current(newVal) {
      this.$emit("input", newVal);
    },
    tabs() {
      this.$nextTick(() => {
        this.getTabItemWidth();
      });
    },
    pills() {
      this.$nextTick(() => {
        this.getTabItemWidth();
      });
    },
  },
  methods: {
    // 判断输出渐变色或背景色
    getColor,
    // 产生随机字符串
    randomString(len) {
      len = len || 32;
      const $chars =
        "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678"; /** **默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
      const maxPos = $chars.length;
      let pwd = "";
      for (let i = 0; i < len; i++) {
        pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
      }
      return pwd;
    },
    // 切换事件
    change(index) {
      if (this.current !== index) {
        this.current = index;

        this.$emit("change", index);
      }
    },
    // 获取左移动位置
    getTabItemWidth() {
      const query = uni
        .createSelectorQuery()
        // #ifndef MP-ALIPAY
        .in(this);
      // #endif
      // 获取容器的宽度
      query
        .select(`#scrollContainer${this.index}`)
        .boundingClientRect((data) => {
          if (!this.containerWidth && data) {
            this.containerWidth = data.width;
            this.height = `${data.height * 2 - 4}rpx`;
          }
        })
        .exec();
      // 获取所有的 tab-item 的宽度
      query
        .selectAll(".smt-tabs__container-item" + this.index)
        .boundingClientRect((data) => {
          if (!data) {
            return;
          }
          let lineLeft = 0;
          let currentWidth = 0;
          if (data) {
            this.pills && (lineLeft = this.pillsMarginX / 2);
            for (let i = 0; i < data.length; i++) {
              if (i < this.current) {
                lineLeft += this.pills
                  ? data[i].width + (this.pillsMarginX - 0)
                  : data[i].width;
              } else if (i === this.current) {
                currentWidth = data[i].width;
              } else {
                break;
              }
            }
          }
          // 当前滑块的宽度
          this.currentWidth = currentWidth;
          // 缩放后的滑块宽度
          this.lineWidth =
            currentWidth * this.lineScale * 1 - this.paddingItemX;
          // 滑块作移动的位置
          this.lineLeft = lineLeft + currentWidth / 2;
          // 胶囊距离左侧的位置
          this.pillsLeft = lineLeft;
          // 计算滚动的距离左侧的位置
          if (this.scroll) {
            this.scrollLeft = this.lineLeft - this.containerWidth / 2;
          }
        })
        .exec();
    },
  },
  mounted() {
    this.elId = "xfjpeter_" + this.randomString();
    this.current = this.value;
    this.$nextTick(() => {
      this.getTabItemWidth();
    });
  },
};
</script>

<style lang="scss" scoped>
.smt-tabs {
  width: 100%;
  box-sizing: border-box;
  overflow: hidden;

  ::-webkit-scrollbar {
    display: none;
  }

  &__container {
    min-width: 100%;
    position: relative;
    display: inline-flex;
    align-items: center;
    white-space: nowrap;
    overflow: hidden;

    &-item {
      display: flex;
      align-items: center;
      height: 100%;
      position: relative;
      z-index: 10;
      transition: all 0.3s;
      white-space: nowrap;
    }

    &-item-pills {
      background: $smt-theme-gray-bg;
      border-radius: 8rpx;
    }

    &-item-pills-active {
      background: none;
    }

    &-line {
      position: absolute;
      bottom: 0;
    }

    &-pills {
      position: absolute;
      z-index: 9;
    }
    &-line,
    &-pills {
      &.animation {
        transition: all 0.3s linear;
      }
    }
  }
}
</style>
